/* -*-c++-*- */
/* osgGIS - GIS Library for OpenSceneGraph
 * Copyright 2007-2008 Glenn Waldron and Pelican Ventures, Inc.
 * http://osggis.org
 *
 * osgGIS is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#ifndef _OSGGIS_COLLECTION_FILTER_H_
#define _OSGGIS_COLLECTION_FILTER_H_ 1

#include <osgGIS/Common>
#include <osgGIS/Filter>
#include <osgGIS/Feature>
#include <osgGIS/Fragment>
#include <osgGIS/AttributedNode>
#include <osg/Node>

namespace osgGIS
{
    /**
     * A filter that collects incoming data and meters it out in batches.
     *
     * Normally, data (such as Feature or Fragment data) passes through a FilterGraph
     * one element at a time. A CollectionFilter will "collect" elements,
     * wait until a checkpoint is reached, and then meter the collected
     * elements out in batches.
     * 
     * Since most filters have the options of processing data either in 
     * batches or one element at a time, a collection filter is useful for
     * combining related features or for enabling optimization. 
     *
     * For example: The CombineLinesFilter optimizes line layers by combining
     * line segments that share endpoints into single line strips, reducing the
     * number of features and helping performance. Since this filter needs to
     * access all incoming features as a group and compare them, you must precede
     * it with a CollectionFilter.
     *
     * Another possible use for a collection filter would be to save the state
     * of the graph to support partial compilation or data caching. This is
     * not yet implemented but will be in the future.
     */
    class OSGGIS_EXPORT CollectionFilter : public Filter
    {
        OSGGIS_META_FILTER( CollectionFilter );  

    public:
        /**
         * Constructs a new collection filter with no metering limit;
         * i.e. it will collect all incoming elements into a single batch.
         */
        CollectionFilter();

        /**
         * Copy constructor.
         */
        CollectionFilter( const CollectionFilter& rhs );


    public: // properties

        /**
         * Sets the metering size. This will determine how many collected
         * elements get sent out in each batch.
         *
         * @param value
         *      Batch size for metered output
         */
        void setMetering( int value ) { metering = value; }

        /**
         * Gets the number of collected elements that will be sent out in each batch.
         *
         * @return Batch size for metered output
         */
        int getMetering() const { return metering; }
        
        /**
         * Sets the name of the FilterEnv property to which to store the name of the
         * current metering group.
         *
         * @param value
         *      FilterEnv property name
         */
        void setAssignmentNameProperty( const std::string& value );
        
        /**
         * Gets the name of the FilterEnv property to which to store the name of the
         * current metering group assignment.
         *
         * @return FilterEnv property name
         */
        const std::string getAssignmentNameProperty() const;
    

    public: // Filter overrides
        FilterState* newState() const;

        virtual void setProperty( const Property& prop );
        virtual Properties getProperties() const;

    public:

        virtual ~CollectionFilter();

    public:

        virtual std::string assign( Feature*, FilterEnv* ) { return ""; }
        virtual std::string assign( Fragment*, FilterEnv* ) { return ""; }
        virtual std::string assign( AttributedNode*, FilterEnv* ) { return ""; }
        
    public:
    
        virtual void preMeter( FeatureList& features, FilterEnv* ) { }
        virtual void preMeter( FragmentList& drawables, FilterEnv* ) { }
        virtual void preMeter( AttributedNodeList& nodes, FilterEnv* ) { }

    private:

        int metering;
        std::string group_property_name;        
        friend class CollectionFilterState;
    };

    
    /**
     * A filter that collects incoming data and meters it out in batches.
     *
     * This class is the same as the CollectionFilter, but exists to change the
     * class name while preserving backwards compatibility.
     *
     * @see CollectionFilter
     */
    class OSGGIS_EXPORT CollectFilter : public CollectionFilter
    {
        OSGGIS_META_FILTER( CollectFilter );  

    public:
        CollectFilter() { }
        CollectFilter( const CollectFilter& rhs ) : CollectionFilter( rhs ) { }
    };
}


#endif // _OSGGIS_COLLECTION_FILTER_H_
